<template>
  <div class="Roles">
    <Breadcrumb name1="权限管理" name2="角色列表" />
    <!-- 卡片视图区域 -->
    <el-card>
      <el-row>
        <!-- 添加角色 -->
        <el-col>
          <el-button type="primary" @click="data.addDialogVisible = true">添加角色</el-button>
        </el-col>
        <el-col>
          <!-- 角色列表 -->
          <el-table :data="data.rolesList" stripe>
            <!-- 展开列 -->
            <el-table-column type="expand">
              <template v-slot="scope">
                <el-row :class="['bdtop', i1 === 0 ? 'bdbottom' : '', 'vcenter']" v-for="(item1, i1) in scope.row.children" :key="item1.id">
                  <!-- 渲染一级权限 -->
                  <el-col :span="5">
                    <el-tag closable @close="removeRightById(scope.row, item1.id)">{{ item1.authName }}</el-tag>
                    <i class="el-icon-caret-right"></i>
                  </el-col>

                  <!-- 渲染二和三级权限 -->
                  <el-col :span="19">
                    <!-- 通过 for 嵌套 渲染二级权限 -->
                    <el-row v-for="(item2, i2) in item1.children" :key="item2.id" :class="[i2 === 0 ? '' : 'bdtop', 'vcenter']">
                      <el-col :span="6">
                        <el-tag type="success" closable @close="removeRightById(scope.row, item2.id)">
                          {{ item2.authName }}
                        </el-tag>
                        <i class="el-icon-caret-right"></i>
                      </el-col>
                      <el-col :span="18">
                        <el-tag type="warning" :class="[i3 === 0 ? '' : 'bdtop']" v-for="(item3, i3) in item2.children" :key="item3.id" closable @close="removeRightById(scope.row, item3.id)">
                          {{ item3.authName }}
                        </el-tag>
                      </el-col>
                    </el-row>
                  </el-col>
                </el-row>
                <!-- <pre>
                  {{ scope.row }}
                </pre> -->
              </template>
            </el-table-column>
            <!-- 索引列 -->
            <el-table-column type="index" label="#"></el-table-column>
            <el-table-column prop="roleName" label="角色名称"></el-table-column>
            <el-table-column prop="roleDesc" label="角色描述"></el-table-column>
            <el-table-column label="操作">
              <template v-slot="scope">
                <el-button size="small" type="primary" icon="el-icon-edit" @click="showEditDialog(scope.row.id)">编辑</el-button>
                <el-button size="small" type="danger" @click="rolesdelete(scope.row.id)" icon="el-icon-delete">删除</el-button>
                <el-button size="small" @click="showSetRightDialog(scope.row)" type="warning" icon="el-icon-search">分配权限</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-col>
      </el-row>
    </el-card>
    <!-- 添加角色对话框 -->
    <el-dialog title="添加角色" v-model="data.addDialogVisible" @close="addDislogClosed">
      <el-form :model="addRolesForm" :rules="addFormRules" ref="addRolesForm" label-width="100px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="addRolesForm.roleName"></el-input>
        </el-form-item>
        <el-form-item label="角色描述" prop="roleDesc">
          <el-input v-model="addRolesForm.roleDesc"></el-input>
        </el-form-item>
      </el-form>
      <span class="dialog-footer">
        <el-button @click="data.addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="addRolesUser">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 编辑对话框 -->
    <el-dialog title="修改角色" v-model="data.editDialogVisible" width="30%">
      <el-form :model="editRolesForm" :rules="editFormRules" ref="editFormRef" label-width="100px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="editRolesForm.roleName"></el-input>
        </el-form-item>
        <el-form-item label="角色描述" prop="roleDesc">
          <el-input v-model="editRolesForm.roleDesc"></el-input>
        </el-form-item>
      </el-form>
      <span class="dialog-footer">
        <el-button @click="data.editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="editFormInfo">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 分配权限的对话框 -->
    <el-dialog title="分配权限" v-model="data.SetRightDialogVisible" width="50%" @close="SetRightDialogVisibleClosed">
      <!-- 树形控件 -->
      <el-tree :data="rightsList" :props="treeProps" show-checkbox node-key="id" :default-expand-all="true" :default-checked-keys="defKeys" ref="treeRef"></el-tree>
      <span class="dialog-footer">
        <el-button @click="data.SetRightDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="allotRights">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script setup>
import Breadcrumb from '@/components/content/breadcrumb/Breadcrumb.vue'
// import { rolesFormRulesMixin } from '@/common/mixin.js'
import axios from '@/utils/axios'
import { onMounted, reactive } from 'vue-demi'
const data = reactive({
  // 所有角色的列表
  rolesList: [],
  // 所有权限的数据
  rightsList: [],
  // 添加角色对话框的显示和隐藏
  addDialogVisible: false,
  // 编辑对话框的显示和隐藏
  editDialogVisible: false,
  // 分配权限对话框的显示和隐藏
  SetRightDialogVisible: false,
  addRolesForm: {
    roleName: '',
    roleDesc: ''
  },
  editRolesForm: {},
  // 树形控件的绑定对象
  treeProps: {
    children: 'children',
    label: 'authName'
  },
  // 树形控件 -> 默认选中的节点id值数组
  defKeys: [],
  // 当前即将分配权限的角色的ID
  rolesId: ''
})
onMounted(() => {
  getRolesList()
})
// 获取角色列表
const getRolesList = async () => {
  const { data: res } = await axios.ajax({
    url: '/roles',
    method: 'GET'
  })
  data.rolesList = res.data
  console.log(data.rolesList.id, 'getRoles')
}
// 添加角色
const addRolesUser = async (formEl) => {
  formEl.validate(async valid => {
    if (!valid) return
    const { data: res } = await this.$http.post('roles', this.addRolesForm)
    console.log(res)
    if (res.meta.status !== 201) {
      return this.$message.error('添加角色失败!')
    }
    getRolesList()
    data.addDialogVisible = false
  })
  // console.log(this.addRolesForm)
}
// 清空添加角色对话框
const addDislogClosed = (formEl) => {
  if (!formEl) return
  formEl.resetFields()
}
// 删除角色
const rolesdelete = async (id) => {
  const confirmRusult = await this.$confirm('此操作将永久删除该角色, 是否继续?', '删除角色', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).catch(err => err)
  // 没有使用await
  if (confirmRusult !== 'confirm') {
    return this.$message.info('已取消该删除操作')
  }
  this.$http.delete('roles/' + id).then(res => {
    const { data: response } = res
    // console.log(response)
    if (response.meta.status !== 200) {
      return this.$message.error('该用户删除失败')
    }
    this.$message.success('该用户已经删除')
    this.getRolesList()
  })
}

// 得到修改用户的信息
const showEditDialog = async (id) => {
  const { data: res } = await this.$http.get('roles/' + id)
  if (res.meta.status !== 200) {
    return this.$message.error('查询角色失败!')
  }
  this.editRolesForm = res.data
  console.log(this.editRolesForm)
  data.editDialogVisible = true
}
const editFormInfo = (formEl) => {
  formEl.validate(valid => {
    if (!valid) return
    this.$http
      .put('roles/' + this.editRolesForm.roleId, {
        roleName: this.editRolesForm.roleName,
        roleDesc: this.editRolesForm.roleDesc
      })
      .then(res => {
        if (res.data.meta.status !== 200) {
          return this.$message.error('修改角色失败!')
        }
        this.$message.success('修改角色成功!')
        this.getRolesList()
      })
    this.editDialogVisible = false
  })
}
// 根据ID删除对应的权限
const removeRightById = async (roles, id) => {
  // 弹框提示用户是否删除
  const confirmResult = await this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).catch(err => err)
  if (confirmResult !== 'confirm') {
    return this.$message.info('取消了删除!')
  }
  const { data: res } = await this.$http.delete(`roles/${roles.id}/rights/${id}`)
  if (res.meta.status !== 200) {
    return this.$message.error('删除权限失败!')
  }
  // this.getRolesList()
  // 直接调用获取用户的方法会导致展开栏的关闭,这样体验不好
  // 可以直接把返回的最新数据直接赋值
  roles.children = res.data
  console.log('删除')
}
// 展示分配权限的对话框
const showSetRightDialog = async (roles) => {
  this.rolesId = roles.id
  // 获取所有权限列表
  const { data: res } = await axios.ajax({
    url: 'rights/tree',
    method: 'GET'
  })
  if (res.meta.status !== 200) {
    return this.$message.error('获取权限列表失败!')
  }
  // 获取到的权限数据保存
  data.rightsList = res.data
  console.log(this.rightsList)
  // 递归获取三级节点
  getLeafKeys(roles, this.defKeys)
  data.SetRightDialogVisible = true
}
// 递归的形式,获取角色下所有的三级权限的id,并保存到 defKeys数组中
const getLeafKeys = (node, arr) => {
  // 如果当前node没有children属性则是三级节点
  if (!node.children) {
    return arr.push(node.id)
  }
  node.children.forEach(item => this.getLeafKeys(item, arr))
}
// 监听分配权限对话框的关闭事件
const SetRightDialogVisibleClosed = () => {
  // 清空 defkeys 数组  避免累积
  this.defKeys = []
}
// 点击为角色分配权限
const allotRights = async () => {
  const keys = [...this.$refs.treeRef.getCheckedKeys(), ...this.$refs.treeRef.getHalfCheckedKeys()]
  const idStr = keys.join(',')
  const { data: res } = await this.$http.post(`roles/${this.rolesId}/rights`, { rids: idStr })
  if (res.meta.status !== 200) {
    return this.$message.error('分配权限失败!')
  }
  this.$message.success('分配权限成功!')
  this.getRolesList()
  this.SetRightDialogVisible = false
}
</script>

<style lang="less" scoped>
.el-table {
  margin-top: 15px;
}
.el-tag {
  margin: 7px;
}
.bdtop {
  border-top: 1px solid #eee;
}
.bdbottom {
  border-bottom: 1px solid #eee;
}

.vcenter {
  display: flex;
  align-items: center;
}
</style>
